#!/usr/bin/env python2

#Avalanche
import wx
import time
import numpy as np

import matplotlib
matplotlib.interactive( True )
matplotlib.use( 'WXAgg' )

from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
from matplotlib.figure import Figure

import os
import sys
import pickle

avalancheDataFolder = "avalanche_data"

if sys.platform[:3] == 'win':
    data_source_path = os.path.join(os.getenv("APPDATA"), avalancheDataFolder)
else : #mac or linux
    data_source_path = os.path.join(os.path.expanduser("~"), "."+avalancheDataFolder)

if not os.path.exists(data_source_path):
    os.mkdir(data_source_path)

INPROGRESS = 0
COMPLETE = 1
INCOMPLETE = 2
DELETE = 3

AVL_MI_QUIT = 1
AVL_MI_SOUND = 2
AVL_MI_CLEAR_USER_DATA = 3

AVL_BI_CHART_BUTTON = 3

AVL_FI_NERD_PLOT = 1

AVL_BS_START = 0
AVL_BS_CANCEL = 1

duration_of_one_second = 1000

def make_fuzzy_date_string(float_time):
    local_time = time.localtime()
    today_start = int((time.time() - local_time.tm_hour * 3600)/3600)*3600
    yesterday_start = today_start - 3600 * 24

    localized_time = time.localtime(float_time)

    if float_time > today_start:
        return time.strftime("%H:%M", localized_time)
    elif float_time > yesterday_start:
        return "Yesterday " + time.strftime("%H:%M", localized_time)
    else:
        return time.strftime("%c", localized_time)

class PlotPanel (wx.Panel):
    """The PlotPanel has a Figure and a Canvas. OnSize events simply set a 
flag, and the actual resizing of the figure is triggered by an Idle event."""
    def __init__( self, parent, color=None, dpi=None, **kwargs ):
        self.parent = parent

        self.look_back_hours = 16

        # initialize Panel
        if 'id' not in kwargs.keys():
            kwargs['id'] = wx.ID_ANY
        if 'style' not in kwargs.keys():
            kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE
        wx.Panel.__init__( self, parent, **kwargs )

        # initialize matplotlib stuff
        self.figure = Figure( None, dpi )
        self.canvas = FigureCanvasWxAgg( self, -1, self.figure )
        self.SetColor( color )

        self._SetSize()

        self._resizeflag = False

        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)
        self.parent.Bind(wx.EVT_CLOSE, self._onClose)

#        self.sample_data = np.array([
#        [time.time()-60*60, 5.0/60.0],
#        [time.time()-70*60, 1.0/60.0],
#        [time.time()-80*60, 10.0/60.0],
#        [time.time()-100*60, 10.0/60.0],
#        [time.time()-200*60, 20.0/60.0],
#        [time.time()-400*60, 20.0/60.0],
#        [time.time()-450*60, 20.0/60.0],
#        [time.time()-461*60, 10.0/60.0],
#        [time.time()-474*60, 10.0/60.0],
#        [time.time()-500*60, 5.0/60.0],
#        [time.time()-548*60, 20.0/60.0],
#        [time.time()-600*60, 5.0/60.0],
#        [time.time()-624*60, 15.0/60.0],
#        [time.time()-800*60, 5.0/60.0],
#        [time.time()-901*60, 1.0/60.0],
#        [time.time()-950*60, 10.0/60.0]
#        ])
#
#        #self.draw()
        
    def SetColor( self, rgbtuple=None ):
        """Set figure and canvas colours to be the same."""
        if rgbtuple is None:
            rgbtuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ).Get()
        clr = [c/255. for c in rgbtuple]
        self.figure.set_facecolor( clr )
        self.figure.set_edgecolor( clr )
        self.canvas.SetBackgroundColour( wx.Colour( *rgbtuple ) )

    def _onClose(self, event):
        self.parent.Show(False)

    def _onSize( self, event ):
        self._resizeflag = True

    def _onIdle( self, evt ):
        if self._resizeflag:
            self._resizeflag = False
            self._SetSize()

    def _SetSize( self ):
        pixels = tuple( self.parent.GetClientSize() )
        self.SetSize( pixels )
        self.canvas.SetSize( pixels )
        self.figure.set_size_inches( float( pixels[0] )/self.figure.get_dpi(),
                                     float( pixels[1] )/self.figure.get_dpi() )

#    def draw(self):
#        """Draw data."""
#        current_hour = np.floor( time.time() / 60 ) * 60
#        ltime = time.localtime()
#        ticktimes = np.arange(ltime.tm_hour-self.look_back_hours,ltime.tm_hour)
#        ticktimes[ticktimes < 0] += 24
#        self.figure.clf()
#        self.subplot = self.figure.add_subplot(1,1,1,title='Recent Performance', 
#                                               xlabel='Time', ylabel='Hours',
#                                               xticks=np.arange(current_hour-self.look_back_hours*3600,time.time(), 3600),
#                                               xticklabels=[str(i) for i in ticktimes],
#                                               xlim=[current_hour-self.look_back_hours*3600, current_hour])
#        self.subplot.plot( self.sample_data[:,0], self.sample_data[:,1], 'o', color=[1.0,0,0],markersize=5, label='Completed Taks')
#        self.subplot.plot( self.sample_data[:,0], np.cumsum(self.sample_data[:,1][::-1])[::-1], '.-', color=[0,0,1.0], markersize=5, label='Cumulative Work')
#        self.subplot.legend(loc='upper left')
#        self.figure.draw()
#        #for i, pt_list in enumerate( self.point_lists ):
#        #    plot_pts = num.array( pt_list )
#        #    clr = [float( c )/255. for c in self.clr_list[i]]

    def draw_task_data(self, completed_start, completed_durations, incomplete_start):
        current_hour = np.floor( time.time() / 3600 ) * 3600
        #print current_hour

        utcticktimes = np.arange(current_hour-self.look_back_hours*3600,time.time()+3600, 3600)

        ltime = time.localtime()
        localticktimes = np.arange(ltime.tm_hour-self.look_back_hours,ltime.tm_hour+1)
        localticktimes[localticktimes < 0] += 24

        look_time = time.time() - self.look_back_hours * 3600
        runningsum_inds = completed_start > look_time
        num_runningsum_inds = runningsum_inds.astype('int').sum()
        
        if num_runningsum_inds == 0:
            completed_ticks = np.array([time.time()])
            completed_data = np.array( [0] )
        
        else:
            completed_ticks = np.zeros(num_runningsum_inds*2+1)
            completed_ticks[:num_runningsum_inds*2:2] = completed_start[runningsum_inds]
            completed_ticks[1:num_runningsum_inds*2:2] = completed_start[runningsum_inds] + completed_durations[runningsum_inds]
            completed_ticks[-1] = time.time()
    
            completed_data = np.zeros(num_runningsum_inds*2+1)
            completed_data[1:num_runningsum_inds*2:2] = completed_durations[runningsum_inds] / 3600.0
            completed_data = np.cumsum(completed_data)
            
        if runningsum_inds.size > 0 and num_runningsum_inds > 0:
            completed_data[-1] = completed_data[-2]        

        try:
            max_cumulative = completed_data.max()
        except:
            max_cumulative = 0
            
        self.figure.clf()
        if hasattr(self, 'subplot'):
            #self.figure.delaxes(self.subplot)
            self.subplot.clear()

        self.subplot = self.figure.add_subplot(1,1,1,title='Recent Performance', 
                                               xlabel='Time', ylabel='Hours',
                                               xticks=utcticktimes,
                                               xticklabels=[str(i)+"h" for i in localticktimes],
                                               xlim=[current_hour-self.look_back_hours*3600, time.time()],
                                               ylim=[0,max(3.0, max_cumulative + 0.5)])

       
        self.subplot.plot( completed_ticks, completed_data, '.-', linewidth=3.0, color=[0,0,1.0], label="%d Hour Cumulative Performance"%self.look_back_hours)

        self.subplot.plot( incomplete_start, np.zeros(incomplete_start.size)+1.0/60.0, 'o', color=[1.0,0,0],markersize=15, label='Incomplete Tasks')
        self.subplot.plot( completed_start+completed_durations, completed_durations/3600.0, 'o', color=[0,1.0,0],markersize=15, label='Completed Taks')

        self.subplot.legend(loc='upper left')

        # self.figure.draw()
        
class MyPopupMenu(wx.Menu):
    def __init__(self, origin):
        wx.Menu.__init__(self)

        self.origin = origin 
        
        #self.WinName = WinName
        item = wx.MenuItem(self, wx.NewId(), "Complete")
        self.AppendItem(item)
        self.Bind(wx.EVT_MENU, self.OnComplete, item)

        item = wx.MenuItem(self, wx.NewId(),"Incomplete")
        self.AppendItem(item)
        self.Bind(wx.EVT_MENU, self.OnIncomplete, item)

        item = wx.MenuItem(self, wx.NewId(),"Delete...")
        self.AppendItem(item)
        self.Bind(wx.EVT_MENU, self.OnDelete, item)

        item = wx.MenuItem(self, wx.NewId(),"Edit Description...")
        self.AppendItem(item)
        self.Bind(wx.EVT_MENU, self.OnEdit, item)

    def OnComplete(self, event):
        self.origin.UpdateSelected(COMPLETE)
        
    def OnIncomplete(self, event):
        self.origin.UpdateSelected(INCOMPLETE)
        
    def OnDelete(self, event):
        self.origin.DeleteSelected()
 
    def OnEdit(self, event):
        self.origin.EditSelectedText()       

class Task:
    def __init__(self, task_str, task_duration, task_status):
        self.str = task_str
        self.duration = task_duration
        self.status = task_status
        self.date = time.time()
        
    def GetStatusStr(self):
        if self.status == INCOMPLETE:
            return "Incomplete"
        elif self.status == COMPLETE:
            return "Complete"
        elif self.status == INPROGRESS:
            return "In progress"
        else:
            return "Unknown"

class TaskTable:
    def __init__(self, wx_origin, source_file=''):
        self.creation_date = time.time()

        self.tasks = []
        self.active_task = 0
        self.source_file = source_file

        if os.path.exists(self.source_file):
            self.Load()

        #information displays
        self.wx_origin = wx_origin

    def GetTimeData(self):
        completed_start_times = []
        completed_durations = []

        incomplete_start_times = []

        for t in self.tasks:
            if t.status == COMPLETE:
                completed_start_times.append(t.date)
                completed_durations.append(t.duration)
            elif t.status == INCOMPLETE:
                incomplete_start_times.append(t.date)
        
        completed_start_times = np.array(completed_start_times)
        completed_durations = np.array(completed_durations)
        incomplete_start_times = np.array(incomplete_start_times)

        sort_ind = np.argsort(completed_start_times)
        completed_start_times = completed_start_times[sort_ind]
        completed_durations = completed_durations[sort_ind]

        return (completed_start_times, completed_durations, incomplete_start_times)

    def AddTask(self,task_str, task_duration, task_status=INPROGRESS):
        self.tasks.append(Task(task_str, task_duration, task_status))
        self.active_task = len(self.tasks) - 1
        self.wx_origin.UpdateDisplayedInformation()
    
        self.Save()

    def ChangeInProgress(self,new_status=COMPLETE):
        self.tasks[self.active_task].status = new_status
        self.wx_origin.UpdateDisplayedInformation()

        self.Save()

    def DeleteInProgress(self):   
        del self.tasks[self.active_task]
        self.wx_origin.UpdateDisplayedInformation()
        
        self.Save()

    def UpdateTaskStatus(self, new_status, task_ids=None):
        if task_ids == None:
            task_ids = [self.active_task]

        #check if any in progress
        for ti in task_ids:
            if self.tasks[ti].status == INPROGRESS:
                return True
           
        for task_id in task_ids:
            self.tasks[task_id].status = new_status 

        self.wx_origin.UpdateDisplayedInformation()
    
        self.Save()

        return False
        
    def DeleteTasks(self, task_ids=None):
        if task_ids == None:
            task_ids = [self.active_task]
        
        #check if any in progress
        for ti in task_ids:
            if self.tasks[ti].status == INPROGRESS:
                return True

        to_keep = list(set(range(len(self.tasks))) - set(task_ids))
        
        self.tasks = [self.tasks[i] for i in to_keep]
        
        self.wx_origin.UpdateDisplayedInformation()
        
        self.Save()

        return False
    
    def Save(self): 
        if self.source_file != '':
            fp = open(self.source_file,"w")
            pickle.dump(self.tasks, fp)
            fp.close()

    def Load(self):
        try:
            fp = file(self.source_file,'r')
            self.tasks = pickle.load(fp)
            fp.close()
        except:
            pass
        for t in self.tasks:
            if t.status == INPROGRESS:
                t.status = INCOMPLETE
    
    def Flush(self):
        self.tasks = []
        self.Save()
        self.wx_origin.UpdateDisplayedInformation()
    
    def UpdateTaskDescription(self,to_edit, new_desc):
        self.tasks[to_edit].str = new_desc
        self.Save()
        self.wx_origin.UpdateDisplayedInformation()
        
class FinisedTaskDialog(wx.Dialog):
    def __init__(self, parent, id, title):
        wx.Dialog.__init__(self,parent,id,title,size=(325,75))
        
        #panel = wx.Panel(self, -1)
        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add(  wx.StaticText(self, label="Plese select the task completion status"),flag=wx.LEFT, border=5)

        hbox = wx.GridSizer(1,3)
        #hbox = wx.BoxSizer(wx.HORIZONTAL)
        self.bt1 = wx.Button(self,-1,"Complete :)")
        self.bt2 = wx.Button(self,-1,"Incomplete :(")
        self.bt3 = wx.Button(self,-1,"Delete from list X")
        hbox.Add(self.bt1,flag=wx.ALIGN_CENTER)
        hbox.Add(self.bt2,flag=wx.ALIGN_CENTER)
        hbox.Add(self.bt3,flag=wx.ALIGN_CENTER)
        vbox.Add(hbox,flag=wx.BOTTOM|wx.TOP, border=5)

        self.Bind(wx.EVT_BUTTON, self.ReturnComplete, id=self.bt1.GetId())
        self.Bind(wx.EVT_BUTTON, self.ReturnInComplete, id=self.bt2.GetId())
        self.Bind(wx.EVT_BUTTON, self.ReturnDelete, id=self.bt3.GetId())

        self.SetSizer(vbox)

    def ReturnComplete(self,event):
        self.EndModal(COMPLETE)

    def ReturnInComplete(self,event):
        self.EndModal(INCOMPLETE)

    def ReturnDelete(self,event):
        self.EndModal(DELETE)

class AvalanchePrefs:
    def __init__(self):
        self.sound = True
        
class Avalanche(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title=title, size=(500,500))

        self.avalanche_prefs = AvalanchePrefs()

        self.cfg = wx.Config('avalanche_config')
        if self.cfg.Exists('sound'):
            self.avalanche_prefs.sound = self.cfg.ReadBool('sound')
        else:
            self.avalanche_prefs.sound = True

        self.nerd_frm = wx.Frame(self, AVL_FI_NERD_PLOT, 'Nerd Plot', size=(600,450))
        self.nerd_panel = PlotPanel( self.nerd_frm )
        
        self.SetIcon(wx.Icon('snow_ball.ico', wx.BITMAP_TYPE_ICO))
        
        self.start_sound = wx.Sound("task_start.wav")
        self.finish_sound = wx.Sound("task_done.wav")
        
        #self.statusbar = self.CreateStatusBar()
        self.summary_text = "Completed: %d\tTotal Time Completed: %d"%(0,0)

        self.task_length = 60

        self.timer = wx.Timer(self,1)
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)

        self.current_task = -1

        #menu bar
        menu = wx.MenuBar()
        file_menu = wx.Menu()
        clear_data = wx.MenuItem(file_menu, AVL_MI_CLEAR_USER_DATA, "Clear Task &History...", "Delete All Tasks Permanently")
        self.Bind(wx.EVT_MENU, self.OnClear, id = AVL_MI_CLEAR_USER_DATA)
        file_menu.AppendItem(clear_data)
        
        quit = wx.MenuItem(file_menu, AVL_MI_QUIT, '&Quit', 'Quit application')
        file_menu.AppendItem(quit)
        self.Bind(wx.EVT_MENU, self.OnQuit, id=AVL_MI_QUIT)
        menu.Append(file_menu, '&File')

        self.options_menu = wx.Menu()
        self.sound_toggle = wx.MenuItem(self.options_menu, AVL_MI_SOUND, "Sounds", "Toggle Sounds", kind=wx.ITEM_CHECK)
        self.options_menu.AppendItem(self.sound_toggle)
        self.options_menu.Check(AVL_MI_SOUND, self.avalanche_prefs.sound)
        self.Bind(wx.EVT_MENU, self.ToggleSound, id=AVL_MI_SOUND)
        menu.Append(self.options_menu, "&Preferences")

        self.help = wx.Menu()
        self.help.Append(wx.ID_ABOUT, '&About')
        self.Bind(wx.EVT_MENU, self.OnAboutBox, id=wx.ID_ABOUT)
        menu.Append(self.help, '&Help')

        self.SetMenuBar(menu)

        #text entry box
        panel = wx.Panel(self, -1)
        vbox = wx.BoxSizer(wx.VERTICAL)

        #Task entering line
        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        st1=wx.StaticText(panel, label="1. Task")
        self.txt = wx.TextCtrl(panel, value="What do you need to do?", size=(200,-1))
        hbox1.Add(st1,flag=wx.RIGHT|wx.LEFT|wx.TOP,border=10)
        hbox1.Add(self.txt, proportion=1, flag=wx.RIGHT|wx.TOP, border=7)
        vbox.Add(hbox1, flag=wx.EXPAND)

        vbox.Add((-1,10))
        #Time entering line
        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        
        gszr1 = wx.GridSizer(1,4,hgap=5)
        st2=wx.StaticText(panel, label="2. Time (minutes)")
        self.rb1=wx.RadioButton(panel,-1,"1", style=wx.RB_GROUP)
        self.rb2=wx.RadioButton(panel,-1,"5")
        self.rb3=wx.RadioButton(panel,-1,"10")
        self.rb4=wx.RadioButton(panel,-1,"20")
        self.Bind(wx.EVT_RADIOBUTTON, self.SetLength, id=self.rb1.GetId())
        self.Bind(wx.EVT_RADIOBUTTON, self.SetLength, id=self.rb2.GetId())
        self.Bind(wx.EVT_RADIOBUTTON, self.SetLength, id=self.rb3.GetId())
        self.Bind(wx.EVT_RADIOBUTTON, self.SetLength, id=self.rb4.GetId())
        
        hbox2.Add(st2, flag=wx.RIGHT|wx.LEFT,border=10)
        gszr1.Add(self.rb1)
        gszr1.Add(self.rb2)
        gszr1.Add(self.rb3)
        gszr1.Add(self.rb4)
        hbox2.Add(gszr1)
        
        vbox.Add(hbox2, flag=wx.EXPAND)

        vbox.Add((-1,10))

        #Start Button
        hbox3 = wx.BoxSizer(wx.HORIZONTAL)
        self.bt1 = wx.Button(panel, id=1, label="3. Go!")
        self.button_state = AVL_BS_START
        self.Bind(wx.EVT_BUTTON, self.OnGoButton,id=1)
        hbox3.Add(self.bt1, flag=wx.RIGHT|wx.LEFT, border=5)

        self.ga1 = wx.Gauge(panel)
        hbox3.Add(self.ga1, proportion=1, flag=wx.RIGHT|wx.LEFT, border = 10)
        vbox.Add(hbox3, flag=wx.EXPAND)        
        
        #hbox4.Add(self.ga1, proportion=1, flag=wx.TOP|wx.RIGHT|wx.LEFT, border = 10)
        #Progress gauge
        #hbox4 = wx.BoxSizer(wx.HORIZONTAL)
        #self.bt2 = wx.Button(panel, id=wx.ID_CANCEL)
        #self.bt2.Disable()
        #self.Bind(wx.EVT_BUTTON, self.OnCancel,id=wx.ID_CANCEL)
        #hbox4.Add(self.bt2,flag=wx.TOP|wx.RIGHT,border=10)
        #vbox.Add(hbox4,flag=wx.EXPAND)
   
        #Task list
        hbox5 = wx.BoxSizer(wx.HORIZONTAL)
        self.lc = wx.ListCtrl(panel, style=wx.LC_REPORT)
        
        self.lc.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
        
        self.lc.InsertColumn(0, 'Task')
        self.lc.InsertColumn(1, 'Duration')
        self.lc.InsertColumn(2, 'Status')
        self.lc.InsertColumn(3, "Start")
        self.lc.SetColumnWidth(0,200)
        self.lc.SetColumnWidth(1,75)
        self.lc.SetColumnWidth(2,100)
        self.lc.SetColumnWidth(3,125)
        
        hbox5.Add(self.lc,flag=wx.EXPAND, proportion=1)
        vbox.Add(hbox5,flag=wx.EXPAND, proportion=1)

        #Information Summary
        self.st2=wx.StaticText(panel, label=self.summary_text)
        hbox6 = wx.BoxSizer(wx.HORIZONTAL)
        hbox6.Add(self.st2, flag=wx.EXPAND|wx.ALL, proportion=1, border = 10)
        self.btchart = wx.BitmapButton(panel, id=AVL_BI_CHART_BUTTON, bitmap=wx.Bitmap('chart-16.png'))
        self.Bind(wx.EVT_BUTTON, self.OnChart,id=AVL_BI_CHART_BUTTON)

        hbox6.Add(self.btchart, flag=wx.ALIGN_RIGHT|wx.RIGHT|wx.TOP|wx.BOTTOM, border=5)

        vbox.Add(hbox6,flag=wx.EXPAND)
        
        panel.SetSizer(vbox)

        self.task_table = TaskTable(self, os.path.join(data_source_path, "user_tasks.pkl") )
        self.lc_to_tl_map = []

        self.UpdateDisplayedInformation()
        self.Show()

    def OnClear(self, event):
        dia = wx.MessageDialog(None, "Are you sure you want to clear all tasks.  This operation is permanent",'Question', wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
        val = dia.ShowModal()

        if val == wx.ID_YES:
            self.task_table.Flush()
        
    def OnChart(self,event):
        if not self.nerd_frm.IsShown():
            completed_start,completed_duration,incomplete_start = self.task_table.GetTimeData()
            self.nerd_panel.draw_task_data(completed_start, completed_duration, incomplete_start)
            self.nerd_frm.Show(True)
        else:
            self.nerd_frm.Show(False)

    def UpdateDisplayedInformation(self):
        #list control
        self.lc.DeleteAllItems()
        self.lc_to_tl_map = []
        for tc,task in enumerate(self.task_table.tasks):
            self.lc.InsertStringItem(0, task.str)
            self.lc.SetStringItem(0,1, str(task.duration / 60))
            self.lc.SetStringItem(0,2, task.GetStatusStr())
            self.lc.SetStringItem(0,3, make_fuzzy_date_string( task.date ) )
            self.lc_to_tl_map.insert(0,tc)
        
        #statusbar
        completed_time = 0
        n_completed = 0
        i = 0
        for t in self.task_table.tasks:
            if t.status == COMPLETE:
                completed_time += t.duration
                n_completed += 1

        completed_time /= 60
        summary_text = "Completed: %d\tTotal Time Completed: %d hours %d minutes"%(
                            n_completed,completed_time/60,completed_time%60)

        self.UpdateSummaryText(summary_text)

        if self.nerd_frm.IsShown():
            completed_start,completed_duration,incomplete_start = self.task_table.GetTimeData()
            self.nerd_panel.draw_task_data(completed_start, completed_duration, incomplete_start)
     
    def EditSelectedText(self):
        index = self.lc.GetFirstSelected()
        to_edit = self.lc_to_tl_map[index]

        dial = wx.TextEntryDialog(None, "Edit the task description", "Task Description", defaultValue=self.task_table.tasks[to_edit].str)
        if dial.ShowModal() == wx.ID_OK:
            self.task_table.UpdateTaskDescription(to_edit, dial.GetValue())
        dial.Destroy()
   
    def DeleteSelected(self):
        index = self.lc.GetFirstSelected()
        to_delete = []
        while index != -1:
            to_delete.append(self.lc_to_tl_map[index])
            index = self.lc.GetNextSelected(index)
        
        num_to_delete = len(to_delete)

        if num_to_delete == 1:
            question = "Are you sure you want to delete the selected task?"
        else:
            question = "Are you sure you want to delete %d tasks?"%(num_to_delete)

        dial = wx.MessageDialog(None, question,'Question', wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
        val = dial.ShowModal()

        if val == wx.ID_YES:
            if (self.task_table.DeleteTasks(to_delete)):
                dial = wx.MessageDialog(None, "You cannot delete a task in progress", "Info", wx.OK|wx.ICON_INFORMATION)
                dial.ShowModal()
                
    def UpdateSelected(self,new_status):
        index = self.lc.GetFirstSelected()
        to_update = []
        while index != -1:
            to_update.append(self.lc_to_tl_map[index])
            index = self.lc.GetNextSelected(index)
        
        if (self.task_table.UpdateTaskStatus(new_status, to_update)):
            dial = wx.MessageDialog(None, "You cannot modify a task in progress", "Info", wx.OK|wx.ICON_INFORMATION)
            dial.ShowModal()

    def UpdateSummaryText(self,status_text):
        self.summary_text = status_text
        self.st2.SetLabel(self.summary_text)

    def ToggleSound(self,event):
        self.avalanche_prefs.sound = self.options_menu.IsChecked(AVL_MI_SOUND)
        self.cfg.WriteBool('sound', self.avalanche_prefs.sound)
        
    def OnRightDown(self,event):
        if self.lc.GetSelectedItemCount() > 0:
            self.PopupMenu(MyPopupMenu(self), event.GetPosition())

    def SetLength(self, event):
        if self.rb1.GetValue(): #one minute
            self.task_length = 60
        elif self.rb2.GetValue():
            self.task_length = 60 * 5
        elif self.rb3.GetValue():
            self.task_length = 60 * 10
        elif self.rb4.GetValue():
            self.task_length = 60 * 20
        
        #print self.task_length
        
    def OnGoButton(self, event):
        if self.button_state==AVL_BS_START:
            self.bt1.SetLabel("Cancel")
            self.button_state = AVL_BS_CANCEL
            self.OnStart()
        else:
            self.bt1.SetLabel("3. Go!")
            self.button_state = AVL_BS_START
            self.OnCancel()
        
    def OnStart(self):
        self.count = 0
        self.timer.Start(duration_of_one_second)

        #print self.txt.GetValue()
        self.task_table.AddTask(self.txt.GetValue(), self.task_length, INPROGRESS)
        if self.avalanche_prefs.sound:
            self.start_sound.Play(wx.SOUND_ASYNC)
    
    def OnCancel(self):
        self.timer.Stop()
        self.ga1.SetValue(0)

        self.task_table.ChangeInProgress(INCOMPLETE)

    def OnQuit(self, event):
        #self.tbIcon.RemoveIcon()
        self.Close(True)

    def OnTimer(self,event):
        self.count = self.count + 1
        self.ga1.SetValue(self.count / float(self.task_length) * 100)
        if self.count == self.task_length:
            self.timer.Stop()
            if self.avalanche_prefs.sound:
                self.finish_sound.Play()
            dia = FinisedTaskDialog(self, -1, "Time is up!")
            val = dia.ShowModal()

            if val == INCOMPLETE:
                self.task_table.ChangeInProgress(INCOMPLETE)
            elif val == DELETE:
                self.task_table.DeleteInProgress()
            else:
                self.task_table.ChangeInProgress(COMPLETE)
                
            #print "returned %d"%val
            dia.Destroy()
        
            self.button_state = AVL_BS_START
            self.bt1.SetLabel("3. Go!")

    def OnAboutBox(self, event):
        description = """Avalanche is a Pomodoro Technique inspired task tracker.  
By encouraging the user to break up their projects into atomic short timed sub-tasks,
it aims to overcome activation barriers and procrastinating behavior.
"""

        licence = """Avalanche is free software; you can redistribute it and/or modify it 
under the terms of the GNU General Public License as published by the Free Software Foundation; 
either version 3 of the License, or (at your option) any later version.

File Hunter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
See the GNU General Public License for more details. You should have received a copy of 
the GNU General Public License along with Avalanche; if not, write to 
the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA"""

        info = wx.AboutDialogInfo()
        
        info.SetIcon(wx.Icon('snow_ball.png', wx.BITMAP_TYPE_PNG))
        info.SetName('Avalanche')
        info.SetVersion('0.1')
        info.SetDescription(description)
        info.SetCopyright('(C) 2011 Mert Dikmen')
        info.SetWebSite('http://code.google.com/p/avalanche-wx')
        info.SetLicence(licence)
        info.AddDeveloper('Mert Dikmen')
        info.AddDocWriter('Mert Dikmen')
        #info.AddArtist('')
        
        wx.AboutBox(info)


if __name__ == '__main__':
    app = wx.App()
    Avalanche(None, -1, title='Avalanche')
    app.MainLoop()
